/*
 *      Copyright 2012-2013 Battams, Derek
 *       
 *       Licensed under the Apache License, Version 2.0 (the "License");
 *       you may not use this file except in compliance with the License.
 *       You may obtain a copy of the License at
 *
 *          http://www.apache.org/licenses/LICENSE-2.0
 *
 *       Unless required by applicable law or agreed to in writing, software
 *       distributed under the License is distributed on an "AS IS" BASIS,
 *       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *       See the License for the specific language governing permissions and
 *       limitations under the License.
 */
package org.schedulesdirect.grabber;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collection;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.client.fluent.Request;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.schedulesdirect.api.Config;
import org.schedulesdirect.api.EpgClient;
import org.schedulesdirect.api.NetworkEpgClient;
import org.schedulesdirect.api.Program;
import org.schedulesdirect.grabber.JsonRequest.RequestAction;
import org.schedulesdirect.grabber.JsonRequest.RequestObject;

/**
 * Downloads program data from the SD service in batch; writing the results to the given VFS
 * 
 * @author Derek Battams &lt;derek@battams.ca&gt;
 *
 */
class ProgramTask implements Runnable {
	static private final Log LOG = LogFactory.getLog(ProgramTask.class);
	
	private JSONArray req;
	private File vfs;
	private NetworkEpgClient clnt;

	/**
	 * Constructor
	 * @param req The array of program ids to be downloaded
	 * @param vfs The name of the vfs being written to
	 * @param clnt The EpgClient to be used to download the request
	 */
	public ProgramTask(Collection<String> progIds, File vfs, NetworkEpgClient clnt) throws JSONException {
		this.req = new JSONArray();
		for(String id : progIds)
			req.put(id);
		this.vfs = vfs;
		this.clnt = clnt;
	}

	@Override
	public void run() {
		long start = System.currentTimeMillis();
		try {
			JsonRequest req = new JsonRequest(clnt.getHash(), clnt.getUserAgent(), clnt.getBaseUrl());
			JSONObject resp = req.submitForJson(RequestAction.GET, RequestObject.PROGRAMS, this.req);
			if(!Utils.isErrorResponse(resp)) {
				String url;
				try {
					url = resp.getString("URL");
				} catch(JSONException e) {
					throw new IOException(e);
				}
				InputStream ins = Request.Get(url).execute().returnContent().asStream();
				if(Config.get().isCaptureZipResponsesActive()) {
					File f = new File(String.format("prog-%s.zip", Thread.currentThread().getName()));
					OutputStream out = new FileOutputStream(f);
					IOUtils.copy(ins, out);
					ins.close();
					out.close();
					ins = new FileInputStream(f);
				}
				ZipInputStream zip = new ZipInputStream(ins);
				LOG.info(String.format("ProgramTask download DONE! [%dms]", System.currentTimeMillis() - start));
				ZipEntry ze;
				while((ze = zip.getNextEntry()) != null) {
					String id = ze.getName();
					if(id.equals(EpgClient.SERVER_ID_ENTRY)) {
						LOG.debug(String.format("Request '%s' handled by %s", req.getTargetUrl(), IOUtils.toString(zip, "UTF-8")));
						continue;
					}
					id = id.substring(0, id.indexOf('.'));
					JSONObject obj = new JSONObject(IOUtils.toString(zip, "UTF-8"));
					Utils.writeVfsEntry(vfs, String.format("programs/%s.txt", id), obj.toString(2));
				}
				LOG.info(String.format("ProgramTask COMPLETE! [%dms]", System.currentTimeMillis() - start));				
			} else
				throw new IOException(resp.optString("message"));
		} catch (IOException e) {
			Grabber.failedTask = true;
			LOG.error("IOError receiving program data; filling in empty program info!", e);
			try {
				JSONArray ids = req;
				for(int i = 0; i < ids.length(); ++i) {
					String id = ids.getString(i);
					Utils.writeVfsEntry(vfs, String.format("programs/%s.txt", id), Program.EMPTY_PROGRAM);
				}
			} catch(Exception x) {
				LOG.error("Unexpected error!", x);
				throw new RuntimeException(x);
			}
		} catch (JSONException e) {
			Grabber.failedTask = true;
			LOG.error("JSONError!", e);
			throw new RuntimeException(e);
		}
	}
}
